<!DOCTYPE html>

<html>

<head>
  <title>使用BufferGeometry</title>
  <script type="text/javascript" src="../three/build/three.js"></script>
  <script type="text/javascript" src="../three/examples/js/controls/OrbitControls.js"></script>
  <script type="text/javascript" src="../three/examples/js/libs/stats.min.js"></script>
  <style>
    body {
      margin: 0;
      overflow: hidden;
    }
  </style>
</head>

<body>

  <div id="Stats-output"></div>
  <div id="WebGL-output"></div>

  <script type="text/javascript">
    var scene, camera, renderer, arrowLineTexture, flowingLineTexture, stats, controls, clock;

    function initScene() {
      scene = new THREE.Scene();
      //用一张图加载为纹理作为场景背景
      scene.background = new THREE.TextureLoader().load("../assets/textures/starry-deep-outer-space-galaxy.jpg");
    }

    function initCamera() {
      camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
      camera.position.set(20, 30, 50);
      camera.lookAt(new THREE.Vector3(0, 0, 0));
    }

    function initLight() {
      //添加环境光
      const ambientLight = new THREE.AmbientLight(0x0c0c0c);
      scene.add(ambientLight);

      const directionalLight = new THREE.DirectionalLight('#fff')
      directionalLight.position.set(30, 30, 30).normalize()
      scene.add(directionalLight)

      //添加聚光灯
      const spotLight = new THREE.SpotLight(0xffffff);
      spotLight.position.set(-40, 60, -10);
      spotLight.castShadow = true;
      scene.add(spotLight);
    }

    function initModel() {
      //drawPointByBufferGeometry();
      //drawLineByBufferGeometry();
      //drawPlaneByBufferGeometry();
      drawPlaneByBufferGeometryUV();
      initPlane();

    }

    function drawPlaneByBufferGeometryUV() {
      //创建BufferGeometry实例
      const bufferGeom = new THREE.BufferGeometry();

      //初始化存放顶点信息的序列化数组
      const positions = new Float32Array([
        -5.0, 3.0, 0.0, //point0
        5.0, 3.0, 0.0, //point1
        6.0, -3.0, 0.0, //point2
        -6.0, -3.0, 0.0, //point3

      ]);

      //设置顶点信息
      bufferGeom.setAttribute('position', new THREE.BufferAttribute(positions, 3));

      //初始化存放颜色信息的序列化数组
      const colors = new Float32Array([
        0.5, 0.3, 0.6,
        0.5, 0.3, 0.6,
        0.5, 0.3, 0.6,
        0.5, 0.3, 0.6,

      ]);
      //设置颜色信息
      bufferGeom.setAttribute('color', new THREE.BufferAttribute(colors, 3));

      const indexs = new Uint16Array([
        0, 1, 2,
        0, 2, 3,
        4, 5, 6,
        4, 6, 7
      ]);

      //设置画面的索引
      bufferGeom.index = new THREE.BufferAttribute(indexs, 1);

      const uvs = new Uint16Array([
        0, 1,
        1, 1,
        1, 0,
        0, 0,

      ]);
      //设置UV
      bufferGeom.setAttribute('uv', new THREE.BufferAttribute(uvs, 2));

      const planetTexture = new THREE.TextureLoader().load("../assets/textures/test.png");

      //创建材质
      const material = new THREE.MeshBasicMaterial({
        map: planetTexture,
        vertexColors: THREE.VertexColors, //使用缓存中的颜色
        side: THREE.DoubleSide
      });

      const mesh = new THREE.Mesh(bufferGeom, material);
      scene.add(mesh);
    }

    function drawPointByBufferGeometry() {
      //创建BufferGeometry实例
      const bufferGeom = new THREE.BufferGeometry();

      //初始化存放顶点信息的序列化数组
      const positions = new Float32Array([
        -5.0, 3.0, 0.0, //point0
        5.0, 3.0, 0.0, //point1
        6.0, -3.0, 0.0, //point2
        -6.0, -3.0, 0.0 //point3
      ]);

      //设置顶点信息
      bufferGeom.setAttribute('position', new THREE.BufferAttribute(positions, 3));

      //创建点材质
      const material = new THREE.PointsMaterial({
        color: 'red',
        size: 2
      });

      const mesh = new THREE.Points(bufferGeom, material);

      scene.add(mesh);
    }

    function drawLineByBufferGeometry() {
      //创建BufferGeometry实例
      const bufferGeom = new THREE.BufferGeometry();

      //初始化存放顶点信息的序列化数组
      const positions = new Float32Array([
        -5.0, 3.0, 0.0, //point0
        5.0, 3.0, 0.0, //point1
        6.0, -3.0, 0.0, //point2
        -6.0, -3.0, 0.0 //point3
      ]);

      //设置顶点信息
      bufferGeom.setAttribute('position', new THREE.BufferAttribute(positions, 3));

      //初始化存放颜色信息的序列化数组
      const colors = new Float32Array([
        1.0, 0.0, 0.0,
        0.0, 1.0, 0.0,
        0.0, 0.0, 1.0,
        0.0, 0.5, 0.5
      ]);
      //设置颜色信息
      bufferGeom.setAttribute('color', new THREE.BufferAttribute(colors, 3));

      const indexs = new Uint16Array([
        0, 1, 2,
        3, 0
      ]);


      //设置画面的索引
      bufferGeom.index = new THREE.BufferAttribute(indexs, 1);

      //创建材质
      const material = new THREE.LineBasicMaterial({
        vertexColors: THREE.VertexColors, //使用缓存中的颜色
        side: THREE.DoubleSide
      });

      const mesh = new THREE.Line(bufferGeom, material);
      scene.add(mesh);
    }

    function drawPlaneByBufferGeometry() {
      //创建BufferGeometry实例
      const bufferGeom = new THREE.BufferGeometry();

      //初始化存放顶点信息的序列化数组
      const positions = new Float32Array([
        -5.0, 3.0, 0.0, //point0
        5.0, 3.0, 0.0, //point1
        6.0, -3.0, 0.0, //point2
        -6.0, -3.0, 0.0 //point3
      ]);

      //设置顶点信息
      bufferGeom.setAttribute('position', new THREE.BufferAttribute(positions, 3));

      //初始化存放颜色信息的序列化数组
      const colors = new Float32Array([
        1.0, 0.0, 0.0,
        0.0, 1.0, 0.0,
        0.0, 0.0, 1.0,
        0.0, 0.5, 0.5
      ]);
      //设置颜色信息
      bufferGeom.setAttribute('color', new THREE.BufferAttribute(colors, 3));

      const indexs = new Uint16Array([
        0, 1, 2,
        0, 2, 3
      ]);


      //设置画面的索引
      bufferGeom.index = new THREE.BufferAttribute(indexs, 1);

      //创建材质
      const material = new THREE.MeshBasicMaterial({
        vertexColors: THREE.VertexColors, //使用缓存中的颜色
        side: THREE.DoubleSide
      });

      const mesh = new THREE.Mesh(bufferGeom, material);
      scene.add(mesh);
    }

    //创建底面
    function initPlane() {
      const planeGeometry = new THREE.PlaneGeometry(50, 50, 1, 1); //创建一个平面几何对象

      //材质
      const planeMaterial = new THREE.MeshLambertMaterial({
        color: 0x080631,
        transparent: true,
        opacity: 0.8
      });
      const plane = new THREE.Mesh(planeGeometry, planeMaterial);

      //设置平面位置
      plane.rotation.x = -0.5 * Math.PI;
      plane.position.set(0, -4, 0);

      //平面添加到场景中
      scene.add(plane);
    }

    //初始化渲染器
    function initRender() {
      renderer = new THREE.WebGLRenderer({
        antialias: true,
        alpha: true
      });
      renderer.setClearColor(0x111111, 1); //设置背景颜色
      renderer.setSize(window.innerWidth, window.innerHeight);
      //renderer.shadowMap.enabled = true; //显示阴影
      document.getElementById("WebGL-output").appendChild(renderer.domElement);
    }
    //初始化轨道控制器
    function initControls() {
      clock = new THREE.Clock(); //创建THREE.Clock对象，用于计算上次调用经过的时间
      controls = new THREE.OrbitControls(camera, renderer.domElement);
      //controls.autoRotate = true; //是否自动旋转
    }


    //性能监控
    function initStats() {
      stats = new Stats();
      stats.setMode(0); //0: fps, 1: ms
      document.getElementById("Stats-output").appendChild(stats.domElement);
    }

    function render() {

      const delta = clock.getDelta(); //获取自上次调用的时间差
      controls.update(delta); //控制器更新
      stats.update();
      requestAnimationFrame(render);
      renderer.render(scene, camera);
    }

    //页面初始化
    function init() {
      initScene();
      initCamera();
      initLight();
      initModel();
      initRender();
      initStats();
      initControls();
      render();
    }

    window.onload = init;
  </script>
</body>

</html>